#include "StdAfx.h"
#include ".\symbioticinterface.h"
#include "SubroutinePopulation.h"
#include "../TermEngine/Terms/ApplicationTerm.h"
#include "Population.h"


void SymbioticInterface::destroy( ){
	if( StemCells ) {
		delete StemCells;
		StemCells = NULL;
		}

	if(CDNAStatementPopulation) {
		delete CDNAStatementPopulation;
		CDNAStatementPopulation = NULL;
		}
	}

SymbioticInterface::SymbioticInterface( EvaluatingTermSet* Genes):
BlockPopulation(Genes), StemCells(NULL), CDNAStatementPopulation(NULL){}

void SymbioticInterface::fillBlockPopulation(void (*Ticker)( void ), bool (*QualityControl)( Token::const_reference)){
	while((BlockPopulation->totalComplexity( ) < BlockPopulationParameters->MaxPopulationSize)||( StemCells->size( ) == 0)){
		const Token& To = SubroutinePopulation::BlockPopulationGenerator( BlockPopulation_FormationRules, QualityControl );
		if((*StemCellRecognizer)(To)) StemCells->push_back( &To );
		if(Ticker) (*Ticker)( );
		}
} 
void SymbioticInterface::generateInitialBlockPopulation( PopulationParameters* PA, 
														bool (*isStemCell) ( const Token&),
														vector< Token::pointer (*) (const Token&)>* Rules,
														void (*Ticker)( void ),
														bool (*QualityControl)( Token::const_reference)){
	destroy( );
	SubroutinePopulation::BlockPopulation(BlockPopulation);
	BlockPopulation_FormationRules = Rules; 
	StemCellRecognizer =	isStemCell;
	StemCells = new vector<const Token*>( );
	BlockPopulationParameters = PA;
	fillBlockPopulation( Ticker, QualityControl );

	}


void SymbioticInterface::countBlockPopulationUse( void (*Ticker)( void ) ){
	//Removes the elements of BlockPopulation that are not 
	//used by any elements in CDNAStatementPopulation
	//side effect, updates BlockUseStats
	if(CDNAStatementPopulation->size( ) <= 0) throw string("Non empty");
	BlockPopulationUseStatistics.erase(BlockPopulationUseStatistics.begin( ), BlockPopulationUseStatistics.end( ));
	for(size_t i=0; i<BlockPopulation->size( ); i++){
		BlockPopulationUseStatistics[&(BlockPopulation->operator[](i))] = 0;
		}
	for(size_t j=0; j<BlockPopulation->Types.size( ); j++){
		BlockPopulationUseStatistics[&((BlockPopulation->Types)[j])] = 0;
		}
	for(size_t k=0; k<CDNAStatementPopulation->Taxonomie.size( ); k++)
		for(size_t l=0; l < ((CDNAStatementPopulation->Taxonomie)[k])->size( ); l++){
			for(size_t m=0; m < ((CDNAStatementPopulation->Taxonomie)[k])->operator[]( l )->size( ); m++){
				const Token* Temp = &(((CDNAStatementPopulation->Taxonomie)[k])->operator[ ]( l )->operator[ ]( m ));
				BlockPopulationUseStatistics[Temp]++;
				}
			if (Ticker) (*Ticker)( );
			}

	}	
void SymbioticInterface::cleanBlockPopulation(void (*Ticker)( void )){
	countBlockPopulationUse(Ticker);
	map<const Token*, size_t>::iterator BlockUseStatsIt = BlockPopulationUseStatistics.begin( );
	vector<const Token*> TempVec;
	while( BlockUseStatsIt != BlockPopulationUseStatistics.end( ) ){
		if(BlockUseStatsIt->second == 0)
			TempVec.push_back(BlockUseStatsIt->first);
		BlockUseStatsIt++;
		if(Ticker) (*Ticker)( );
		}

	for(size_t i=0; i<TempVec.size( ); i++){
		if(	(TempVec[i]->isTerm( )) && ( !(BlockPopulation->isPrimitive(*(TempVec[i]))))){
			BlockPopulation->remove(*(TempVec[i]));
			BlockPopulationUseStatistics.erase(TempVec[i]);
			}
		if(Ticker) (*Ticker)( );
	}
}				
void SymbioticInterface::generateCDNAStatementPopulation( PopulationParameters* PA, const Type* Ty, bool (*Ticker)( void )){
	if(StemCells->empty( )) throw "Tantrum";
	SubroutinePopulation::StemCells(this->StemCells);
	SubroutinePopulation::GoalType(Ty);
	CDNAStatementPopulation = new Population(
		&(SubroutinePopulation::CDNAStatementPopulationGenerator), 
		&(SubroutinePopulation::CDNAStatementSpawner),
		&(SubroutinePopulation::CDNAStatementMutator),	
		PA, 
		Ticker);
	cleanBlockPopulation(  );
	
	}			  


SymbioticInterface::~SymbioticInterface(void)
	{
		destroy( );
	}





